package ar.com.quickMart.database.mysql;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import ar.com.quickMart.database.ListDao;
import ar.com.quickMart.database.quickMartDB;
import ar.com.quickMart.logic.Branch;
import ar.com.quickMart.logic.HistoryList;
import ar.com.quickMart.logic.Product;
import ar.com.quickMart.logic.PromotedProduct;
import ar.com.quickMart.logic.Promotion;
import ar.com.quickMart.logic.Purchasable;
import ar.com.quickMart.logic.QuickMartList;
import ar.com.quickMart.logic.SuperMarket;

public class ListDaoMySql extends BaseDaoMySql implements ListDao{

	/**
	 * 
	 * addProductToList
	 * 
	 * Agrega un producto a una lista existente en la BDD.
	 * 
	 * 	 * 
	 * @param 	listId			Id de la lista a la cual agregar el producto
	 * @param 	productBarcode	Codigo de barras del producto a agregar
	 * @param 	price			Precio unitario del producto
	 * @param 	number			Cantidad a agregar del producto
	 * @return	true			En caso de exito
	 * 			false			En caso contrario
	 */
	public boolean addProductToList(long listId, long productBarcode, Float price, int number) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query de insercion
		String query = "INSERT INTO Lista_has_Producto (Lista_id, Producto_CodBarra, Precio, Cantidad) VALUES (? , ?, ?, ?)";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			statement.setLong(2, productBarcode);
			if(price != null){
				statement.setFloat(3, price);
			}
			else{
				statement.setNull(3, java.sql.Types.FLOAT);
			}
			
			statement.setInt(4, number);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al agregar producto en lista, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Producto agregado a lista, devuelvo true
		return true;
	}
	
	/**
	 * 
	 * removeProductFromList
	 * 
	 * Elimina un producto de una lista
	 * 
	 * @param 	listId				Lista de la cual se quiere eliminar un producto
	 * @param 	productBarcode		Codigo de barras del producto a eliminar
	 * @return	true				En caso de exito
	 * 			false				En caso contrario
	 */
	public boolean removeProductFromList(long listId, long productBarcode) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo los querys
		String query = "DELETE FROM Lista_has_Producto WHERE Lista_id = ? AND Producto_CodBarra = ?; ";

		try {
			
			// Creo las sentencias y ejecuto ambas querys
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			statement.setLong(2, productBarcode);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al eliminar producto de lista, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Producto eliminado de lista, devuelvo true
		return true;
	}
	
	@Override
	public boolean updateProductOnList(long listId, long productBarcode,
			Float price, int number) {
		
		int rowsCount;
		
		// Creo variable para la conexion
		Connection connection;
				
		// Abro la conexion
		connection = connect();
				
		// Creo el query del update
		String query = "UPDATE Lista_has_Producto  SET Precio = ?, Cantidad = ? where Lista_id = ? AND Producto_CodBarra = ?";

				try {		
					// Creo la sentencia y ejecuto el query
					PreparedStatement statement = connection.prepareStatement(query);
					
					if(price != null){
						statement.setFloat(1, price);
					}
					else{
						statement.setNull(1, java.sql.Types.FLOAT);
					}
					statement.setInt(2, number);
					statement.setLong(3, listId);
					statement.setLong(4, productBarcode);
					rowsCount = statement.executeUpdate();
				}
				catch (Exception ex) {
					ex.printStackTrace();
					
					// Desconecto de la BDD
					disconnect(connection);
					
					// Error al agregar producto en lista, devuelvo false
					return false;
				}
				
				// Desconecto de la BDD
				disconnect(connection);
				
				if(rowsCount > 0) {
					return true;
				}
				return false;
	}


	@Override
	public boolean updateProductOnList(long listId, long productBarcode,
			int number) {
		int rowsCount;
		
		// Creo variable para la conexion
		Connection connection;
				
		// Abro la conexion
		connection = connect();
				
		// Creo el query del update
		String query = "UPDATE Lista_has_Producto  SET Cantidad = ? where Lista_id = ? AND Producto_CodBarra = ?";

				try {		
					// Creo la sentencia y ejecuto el query
					PreparedStatement statement = connection.prepareStatement(query);
					
					
					statement.setInt(1, number);
					statement.setLong(2, listId);
					statement.setLong(3,productBarcode);
					rowsCount = statement.executeUpdate();
				}
				catch (Exception ex) {
					ex.printStackTrace();
					
					// Desconecto de la BDD
					disconnect(connection);
					
					// Error al agregar producto en lista, devuelvo false
					return false;
				}
				
				// Desconecto de la BDD
				disconnect(connection);
				
				if(rowsCount > 0) {
					return true;
				}
				return false;
	}
	
	/**
	 * 
	 * addList
	 * 
	 * Agrega una lista de un usuario con un nombre a la BDD.
	 * 
	 * @param 	name		Nombre de la lista a crear
	 * @param 	userId		Id del usuario que crea la lista
	 * @param	branchId	Id de la sucursal, es en caso de asociar la lista a un supermercado. Puede ser null
	 * @return	true		En caso de exito
	 * 			false		En caso contrario
	 */
	public boolean addList(String name, long userId, long branchId) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query de insercion
		String query = "INSERT INTO Lista (NombreLista, Usuario_id, Sucursal_id) VALUES ( ?, ?, ?);";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, name);
			statement.setLong(2, userId);
			statement.setLong(3, branchId);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al agregar estado de compra, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Estado de compra agregado, devuelvo true
		return true;
	}

	/**
	 * 
	 * addList
	 * 
	 * Agrega una lista de un usuario con un nombre a la BDD. (Sin utilizar el BranchId)
	 * 
	 * @param 	name		Nombre de la lista a crear
	 * @param 	userId		Id del usuario que crea la lista
	 * @return	true		En caso de exito
	 * 			false		En caso contrario
	 */
	public boolean addList(String name, long userId) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query de insercion
		String query = "INSERT INTO Lista (NombreLista, Usuario_id) VALUES ( ?, ?);";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, name);
			statement.setLong(2, userId);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al agregar la lista, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Lista agregada, devuelvo true
		return true;
	}
	
	@Override
	public boolean updateListBranchId(long listId, long branchId) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		int rowCount; //tuplas afectadas por el update.
		
		// Creo el query de insercion
		String query = "UPDATE lista SET Sucursal_id = ? WHERE idLista = ?;";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, branchId);
			statement.setLong(2, listId);
			//statement.setLong(3, (Long) null);
			rowCount = statement.executeUpdate();
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al agregar la lista, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Lista agregada, devuelvo true
		
		if(rowCount > 0){
			return true;
		}
		else{
			return false;
		}
		
	}
	
	public boolean updateListName(long listId, String newListName){
		
		// Creo variable para la conexion
		Connection connection;
				
		// Abro la conexion
		connection = connect();
				
		int rowCount; //tuplas afectadas por el update.
				
		// Creo el query de insercion
		String query = "UPDATE lista SET NombreLista = ? WHERE idLista = ?;";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, newListName);
			statement.setLong(2, listId);
			//statement.setLong(3, (Long) null);
			rowCount = statement.executeUpdate();
					
		}
		catch (Exception ex) {
			ex.printStackTrace();
					
			// Desconecto de la BDD
			disconnect(connection);
					
			// Error al agregar la lista, devuelvo false
			return false;
		}
				
		// Desconecto de la BDD
		disconnect(connection);
				
		// Lista agregada, devuelvo true
				
		if(rowCount > 0){
			return true;
		}
		else{
			return false;
		}
	}
	
	/**
	 * 
	 * removeList
	 * 
	 * Elimina una lista de productos perteneciente a un usuario.
	 * 
	 * @param 	listId	Id de la lista a borrar
	 * @return	true	En caso de exito
	 * 			false	En caso contrario
	 */
	public boolean removeList(long listId) {
		
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo los querys
		String queryProducts = "DELETE FROM Lista_has_Producto WHERE Lista_id = ?; ";
		String queryList = "DELETE FROM Lista WHERE idLista = ?; ";
		

		try {
			//desactivo el autoCommit para que no se guarden los cambios luego de cada sentencia
			connection.setAutoCommit(false);
			
			// Creo las sentencias y ejecuto ambas querys
			PreparedStatement statement = connection.prepareStatement(queryProducts);
			statement.setLong(1, listId);		
			statement.executeUpdate();
			
			statement = connection.prepareStatement(queryList);
			statement.setLong(1, listId);		
			statement.executeUpdate();
			
			connection.commit();
			
			connection.setAutoCommit(true);
			
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			try {
				connection.rollback();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al eliminar lista, devuelvo false
			return false;
		}
		
		
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Lista eliminada, devuelvo true
		return true;
	}
	
	public List<String> getListsNames(long userId){
		
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		List<String> listsNames = new ArrayList<String>();
		
		// Creo el query
		String query = "SELECT L.NombreLista FROM Lista L LEFT JOIN Compra C ON L.idLista = C.Lista_id WHERE C.id IS NULL AND Usuario_Id = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, userId);
			
			ResultSet result;
			
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			while(result.next()) {
				listsNames.add(result.getString("NombreLista"));
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			

			return null;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		return listsNames;
	}
	
	public Long getListId(String listName, long userId){
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		Long id;
		
		// Creo el query
		String query = "SELECT idLista FROM Lista WHERE NombreLista = ? AND Usuario_id = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setString(1, listName);
			statement.setLong(2, userId);
			
			ResultSet result;
			
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			if(result.next()) {
				id = result.getLong("idLista");
			}
			else{
				id = null;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			

			return null;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		return id;
	}
	
	public List<Product> getListProducts(long userId, String listName){
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		List<Product> items = new ArrayList<Product>();
		
		// Creo el query para los productos
		String queryProducts = "SELECT P.Nombre, P.CodBarra, L.Cantidad, L.Precio "+
				" FROM Producto P "+
				" JOIN  Lista_has_Producto L ON P.CodBarra = L.Producto_CodBarra " +
				" JOIN Lista LI ON LI.idLista = L.Lista_id "+
				" WHERE LI.NombreLista = ? "+
				" AND LI.Usuario_id = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(queryProducts);
			statement.setString(1, listName);
			statement.setLong(2, userId);
			
			ResultSet result;
			
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			while(result.next()) {
				Product p = new Product();
				
				p.setCode(result.getLong("CodBarra"));
				p.setCount(result.getInt("Cantidad"));
				p.setDescription(result.getString("Nombre"));
				p.setPrice(result.getFloat("Precio"));
				
				items.add(p);
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);

			return null;
		}
		
		
		// Desconecto de la BDD
		disconnect(connection);
		
		if(items.size() > 0){
			return items;
		}
		else{
			return null;
		}
	}
	
	public List<Promotion> getListPromotions(long userId, String listName, boolean includePromotionProducts){
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		List<Promotion> items = new ArrayList<Promotion>();
		
		// Creo el query para los productos
		String queryPromotions = "SELECT P.Descripcion, P.id, P.FechaInicio, P.FechaFin, P.Precio, L.Cantidad "+
		" FROM Promocion P "+
		" JOIN  Lista_has_Promocion L ON P.id = L.Promocion_id "+
		" JOIN Lista LI ON LI.idLista = L.Lista_idLista "+
		" WHERE LI.NombreLista = ? "+
		" AND LI.Usuario_id = ?;";

		try {
	
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(queryPromotions);
			statement.setString(1, listName);
			statement.setLong(2, userId);
	
			ResultSet result;
	
			result = statement.executeQuery();
			result = statement.getResultSet();
	
			while(result.next()) {
				Promotion pr = new Promotion();
		
				pr.setCode(result.getLong("id"));
				pr.setDescription(result.getString("Descripcion"));
				pr.setCount(result.getInt("Cantidad"));
				
				Timestamp timeStamp = result.getTimestamp("FechaInicio");
				pr.setStartDate(new Date(timeStamp.getTime()));
				
				timeStamp = result.getTimestamp("FechaFin");	
				pr.setEndingDate(new Date(timeStamp.getTime()));
				
				pr.setPrice(result.getFloat("Precio"));
				
				items.add(pr);
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);

			return null;
		}
		
		
		if(includePromotionProducts){
			for(Promotion pr : items){
				
				List<Product> products = quickMartDB.getPromotionDao().getPromotionProducts(pr.getCode());
				
				pr.setProducts(products);
			}
		}
		
		
		
		// Desconecto de la BDD
		disconnect(connection);
		
		if(items.size() > 0){
			return items;
		}
		else{
			return null;
		}
	}

	@Override
	public boolean addPromotionToList(long listId, long promotionId,
			int count) {
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo el query de insercion
		String query = "INSERT INTO Lista_has_Promocion (Lista_idLista, Promocion_id,  Cantidad) VALUES (?, ?, ?)";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			statement.setLong(2, promotionId);
			statement.setLong(3, count);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			

			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		

		return true;
	}
	
	@Override
	public boolean updatePromotionOnList(long listId, long promotionId,
			int count) {
		// Creo variable para la conexion
		Connection connection;
				
		// Abro la conexion
		connection = connect();
				
		// Creo el query
		String query = "UPDATE Lista_has_Promocion SET Cantidad = ? WHERE Lista_idLista = ? AND Promocion_id = ?;";

		try {		
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, count);
			statement.setLong(2, listId);
			statement.setLong(3, promotionId);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
					
			// Desconecto de la BDD
			disconnect(connection);
					
			
			return false;
		}
				
		// Desconecto de la BDD
		disconnect(connection);
				
		// Producto agregado a lista, devuelvo true
		return true;
	}

	@Override
	public boolean removePromotionFromList(long listId, long promotionId) {
		// Creo variable para la conexion
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		// Creo los querys
		String query = "DELETE FROM Lista_has_Promocion WHERE Lista_idLista = ? AND Promocion_id = ?";

		try {
			
			// Creo las sentencias y ejecuto ambas querys
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			statement.setLong(2, promotionId);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
			
			// Error al eliminar producto de lista, devuelvo false
			return false;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		// Producto eliminado de lista, devuelvo true
		return true;
	}
	
	public boolean removeAllPromotionFromLis(long listId){
		
		// Creo variable para la conexion
		Connection connection;
				
		// Abro la conexion
		connection = connect();
				
		// Creo los querys
		String query = "DELETE FROM Lista_has_Promocion WHERE Lista_idLista = ? ";

		try {
					
			// Creo las sentencias y ejecuto ambas querys
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, listId);
			statement.executeUpdate();
		}
		catch (Exception ex) {
			ex.printStackTrace();
					
			// Desconecto de la BDD
			disconnect(connection);
					

			return false;
		}
				
		// Desconecto de la BDD
		disconnect(connection);
				

		return true;
	}

	@Override
	public Long getListBranchId(long listId) {
		
		Connection connection;
	
		// Abro la conexion
		connection = connect();
	
		Long id;
	
		// Creo el query
		String query = "SELECT Sucursal_id FROM Lista WHERE idLista = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);;
			statement.setLong(1, listId);
			
			ResultSet result;
		
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			if(result.next()) {
				
				id = result.getLong("Sucursal_id");
				if(result.wasNull()){
					
					disconnect(connection);
					return null;//TODO: hacer esto en todas las lecturas de nulleables
				}
			}
			else{
				id = null;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
		

			return null;
		}
	
		// Desconecto de la BDD
		disconnect(connection);
	
		return id;
	}

	@Override
	public QuickMartList getQuickMartList(String listName, long userId) {
		Connection connection;
		
		// Abro la conexion
		connection = connect();
	
		QuickMartList list;
	
		// Creo el query
		String query = "SELECT L.idLista, L.NombreLista " +
				" FROM Lista L " +
				" LEFT JOIN Compra C ON L.idLista = C.Lista_id " +
				" WHERE C.id IS NULL " +
				" AND NombreLista = ? " +
				" AND Usuario_id = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);;
			statement.setString(1, listName);
			statement.setLong(2, userId);
			
			ResultSet result;
		
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			if(result.next()) {
				
				list = new QuickMartList();
				
				list.setId(result.getLong("idLista"));
				list.setName(result.getString("NombreLista"));

			}
			else{
				list = null;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
		

			return null;
		}
	
		// Desconecto de la BDD
		disconnect(connection);
	
		if(list != null){
			
			List<Product> products = this.getListProducts(userId, listName);
			
			list.setItems(new ArrayList<Purchasable>());
			if(products != null){
				
				list.getItems().addAll(products);
			}
			
			List<Promotion> promotions = this.getListPromotions(userId, listName, false);
			
			if(promotions != null){
				
				list.getItems().addAll(promotions);
				list.setHasPromotions(true);
			}
			else{
				list.setHasPromotions(false);
			}
		}
		
		return list;
	}
	
	@Override
	public List<QuickMartList> getQuickMartLists(long userId) {
		Connection connection;
		
		// Abro la conexion
		connection = connect();
	
		List<QuickMartList> lists =  new ArrayList<QuickMartList>();
	
		// Creo el query
		String query = "SELECT L.idLista, L.NombreLista, S.Direccion As sucursal, SUP.nombre AS supNombre, SUP.id AS supId "+
				" FROM Lista L " +
				" LEFT JOIN Compra C ON L.idLista = C.Lista_id " +
				" LEFT JOIN Sucursal S ON L.Sucursal_id = S.id " +
				" LEFT JOIN Supermercado SUP ON S.Supermercado_id = SUP.id "+
				" WHERE C.id IS NULL " +
				" AND Usuario_id = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);;
			statement.setLong(1, userId);
			
			ResultSet result;
		
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			while(result.next()) {
				
				QuickMartList list= new QuickMartList();
				
				list.setId(result.getLong("idLista"));
				list.setName(result.getString("NombreLista"));
				
				
				list.setBranch(new Branch());
				list.getBranch().setAddress(result.getString("sucursal"));
				if(!result.wasNull()){
					list.getBranch().setSuperMarket(new SuperMarket());
					
					list.getBranch().getSuperMarket().setName(result.getString("supNombre"));
					list.getBranch().getSuperMarket().setId(result.getLong("supId"));
					
				}
				else{
					list.setBranch(null);
				}
				
				lists.add(list);
		
			}

		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);
		

			return null;
		}
	
		// Desconecto de la BDD
		disconnect(connection);
	
		
		if(lists.size() == 0){
			return null;
		}
		else{
			return lists;
		}
		
		
	}

	@Override//TODO: ver el tema de las excepciones
	public boolean updateProductsPrices(long listId, List<Long> barCodes,
			List<Float> newPrices) {
		
		// Creo variable para la conexion
		Connection connection;
						
		// Abro la conexion
		connection = connect();
						
		// Creo el query del update
		String query = "UPDATE Lista_has_Producto  SET Precio = ? where Lista_id = ? AND Producto_CodBarra = ?";

		try {
			connection.setAutoCommit(false);
			
		} catch (SQLException e) {
			
			e.printStackTrace();
			disconnect(connection);
			return false;
		}
		
		for(int x=0; x < barCodes.size(); x++){
			try {		
				// Creo la sentencia y ejecuto el query
				PreparedStatement statement = connection.prepareStatement(query);
								

				statement.setFloat(1, newPrices.get(x));

				statement.setLong(2, listId);
				statement.setLong(3, barCodes.get(x));
				statement.executeUpdate();
			}
			catch (Exception ex) {
				ex.printStackTrace();
								
				try {
					connection.rollback();
				} catch (SQLException e) {
					e.printStackTrace();
				}
				
				// Desconecto de la BDD
				disconnect(connection);
								
				// Error al agregar producto en lista, devuelvo false
				return false;
			}
		}
		
		try {
			connection.commit();
		} catch (SQLException e) {
			
			e.printStackTrace();	
			disconnect(connection);
			return false;
		}
		
		
		// Desconecto de la BDD
		disconnect(connection);
						

		return true;
	}


	public List<HistoryList> getHistoryList(long userId){
		Connection connection;
		
		// Abro la conexion
		connection = connect();
		
		List<HistoryList> historyLists = new ArrayList<HistoryList>();
		
		// Creo el query
		String query = "SELECT L.idLista, L.NombreLista, C.Fecha, C.ImporteTotal, E.Descripcion " +
		" FROM Lista L, Compra C, Estadodecompra E " +
		" WHERE L.idLista = C.Lista_id" +
		" AND C.EstadoDeCompra_id = E.id"+
		" AND C.id IS NOT NULL " +
		" AND Usuario_id = ?;";

		try {
			
			// Creo la sentencia y ejecuto el query
			PreparedStatement statement = connection.prepareStatement(query);
			statement.setLong(1, userId);
			
			ResultSet result;
			
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			while(result.next()) {
				HistoryList hList = new HistoryList(); 
				
				hList.setId(result.getLong("idLista"));
				hList.setName(result.getString("NombreLista"));
				hList.setTotalToPay(result.getFloat("ImporteTotal"));
				hList.setState(result.getString("Descripcion"));
				
				Timestamp timeStamp = result.getTimestamp("Fecha");
				hList.setConfirmationDate(new Date(timeStamp.getTime()));
				
				historyLists.add(hList);
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			// Desconecto de la BDD
			disconnect(connection);

			return null;
		}
		
		// Desconecto de la BDD
		disconnect(connection);
		
		return historyLists;
	}

	@Override
	public boolean cloneList(String listName, long userId, String newListName) {
		
		
		//obtengo los productos
		List<Product> products = this.getListProducts(userId, listName);
			
		//registrar la lista
		
		// Creo variable para la conexion
		Connection connection;
				
		// Abro la conexion
		connection = connect();
		
		try {
			connection.setAutoCommit(false);
		} catch (SQLException e) {
			
			e.printStackTrace();
		}
				
		// Creo el query de insercion
		String queryList = "INSERT INTO Lista (NombreLista, Usuario_id) VALUES ( ?, ?);";
		String queryGetId = "SELECT idLista FROM Lista WHERE NombreLista = ? AND Usuario_id = ?;";
		String queryProducts = "INSERT INTO Lista_has_Producto (Lista_id, Producto_CodBarra, Precio, Cantidad) VALUES (? , ?, ?, ?)";

		try {		
			// registro la nueva lista
			PreparedStatement statement = connection.prepareStatement(queryList);
			statement.setString(1, newListName);
			statement.setLong(2, userId);
			statement.executeUpdate();
			
			//obtengo el id de la nueva lista
			Long listId = null;
			statement = connection.prepareStatement(queryGetId);
			statement.setString(1, newListName);
			statement.setLong(2, userId);
			
			ResultSet result;
			
			result = statement.executeQuery();
			result = statement.getResultSet();
			
			if(result.next()) {
				listId = result.getLong("idLista");
			}
			
			if(listId == null){
				connection.rollback();
				System.out.println("new list registry fail");
				disconnect(connection);
				return false;
			}
			
			//registro los productos
			statement = connection.prepareStatement(queryProducts);
			
			for(Product p : products){
				
				statement.setLong(1, listId);
				statement.setLong(2, p.getCode());
				statement.setFloat(3, 0);//se ponen los precios en 0 para que luego se reasocie la lista
				statement.setInt(4, p.getCount());
				
				statement.executeUpdate();
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			
			try {
				connection.rollback();
			} catch (SQLException e) {
				
				e.printStackTrace();
			}
			
			// Desconecto de la BDD
			disconnect(connection);
					
			// Error al agregar la lista, devuelvo false
			return false;
		}
		
		try {
			connection.commit();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
				
		// Desconecto de la BDD
		disconnect(connection);
		
		return true;
	}

	

	
}
